home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-08-07 | 27.0 KB | 915 lines | [TEXT/PJMM] |
- unit xTextWindow;
-
- { This unit provides support for a text editing window, similar to that used in }
- { TeachText. The window can support only a limited number of characters. The }
- { absolute limit is about 32000, but performance degrades long before that. }
- { The window will have one vertical scroll bar, which is used to scroll the text. }
- { All mouse and editing operations are supported. A procedure twUpdateEditMenu }
- { is exported which can be used to enable or disable the entries in the Edit Menu }
- { according to the state of the front window. The text in the window can be "locked"; }
- { If it is, no editing operations are allowed. }
- { You can leave space at the top and at the right of the edit text. This space could }
- { be used for xWindowDecorations. (However, note that an xTextWindow will be }
- { compatible with an xWindowDecoration of class xStringInput only if the edit text }
- { is locked; otherwise, all keystrokes are sent to the edit text, and the xStringInput }
- { can't be used.) }
-
- interface
-
- uses
- xWindow;
-
-
- type
-
- xTextWindow = object(xWindow) { a window for displaying and/or editing text }
-
- TE: TEHandle; { handle to a standard Mac TEdit data structure }
- linesInTE: integer; { number of lines currently in edit text }
- linesPerPage: integer; { number of lines to scroll for a click in the gray }
- { area of the scroll bar }
- topLeftChar: integer; { the number of the first character currently on screen }
- topTextOffset: integer; { space left in window above edit text }
- leftTextOffset: integer; { space left in window to the left of window }
- maxChars: integer; { maximum characters allowed in text before it is "trimmed" }
- { if the number of characters in the window exceed this limit by }
- { 2000 characters, lines are trimmed from the beginning of the }
- { text to bring the number of characters below maxChars. The }
- { value for maxChars is forced into the range 3000 .. 30000. }
- trimmed: boolean; { this is set to false at the same times changed is set to false, }
- { and is set to true when the window is trimmed. }
- locked: boolean; { set to true when the text is locked }
- changed: boolean; { set to true whenever the text is modified }
- cursorHandler: xWindowDecoration; { used to display an iBeamCursor when }
- { the cursor is over the edit text. }
- tabCt: integer; { tabs are set every tabCt spaces; the default is 1, so that}
- { ordinarily, tabs act just like spaces }
-
- procedure SetDefaults;
- override;
- { sets up the widow to have a vertical scroll bar but no horizontal scroll bar, }
- { with no extra space at the top or left of the text. Also sets maxChars = 10000 }
- { and locked = false. }
- { NOTE: If you change the window to have a horizontal scroll bar, then the window }
- { will not use autowrap; user must press return to start a new line. }
- procedure xTextWindow.openInRect (title: string;
- left, top, right, bottom: integer);
- override;
- { open a text window in the given rectangle; you can also simply use }
- { open(title). these procedures have the same meaning as for xWindow. }
- procedure clearAllText;
- { delete all the text in the window, leaving the window empty }
- procedure installText (theText: CharsHandle);
- { throw away any current text in the window and replace it with theText }
- function getText: CharsHandle;
- { return a handle to the text in the window; this is a handle to the actual }
- { text being used in the TEdit, NOT A COPY }
- procedure InsertString (str: string);
- { add the given string to the window at the current insertion point, or at the }
- { start of the currently hilited range if ther is one; the window is scrolled if }
- { necessary so that at least the start of the inserted string is visible. Note that }
- { this might cause "trimming" of the text if it grows beyond the maximum length. }
- procedure appendString (str: string);
- { adds str to the end of the text by moving the insertion point to the end }
- { of the text, then calling InsertString; scrolling and trimming may occur }
- procedure appendCR;
- { adds a carriage return to the end of the text (by calling }
- { appendString(chr(13))); scrolling and trimming may occur. }
-
- procedure lock;
- { after this is called, the user cannot edit the text; clicking, keystrokes and }
- { Edit menu commands are disabled, and no blinking insertion point is shown. }
- { If you want a window that simply displayed text that the user can read, call }
- { this immediately after opening the window. (Note that YOU can still change }
- { the text with the procedures listed above. }
- procedure unlock;
- { Remove the lock on user editing of the text. }
-
- procedure declareClean;
- function dirty: boolean;
- { These are provided mostly when you are working with files. "Dirty" }
- { will return true whenever the contents of the window need to be saved }
- { because they have beenn changed in some way. When you save the contents, }
- { you should call declareClean. This is called automatically when you call }
- { clearText (probably in response to a New command), or installText }
- { (probably when you load a file.) }
-
- procedure setFont (fontNumber, pointSize: integer);
- { When you open a window, it is set to display its text in a default style }
- { (the application font, probably Geneva) and size (12 point). }
- { You can change the font and size, but only for all the text at once, with }
- { this procedure. The TEdit used in this record does not support mixed }
- { fonts or sizes. The font number will probably be one of the predefined }
- { font names, such as Geneva, NewYork, Monaco, Venice, SystemFont. }
-
- procedure scrollToSelection;
- { Scroll the screen if necessary so that the start of the selection range, }
- { or the insertion point, is visible }
- procedure scrollTo (position: integer);
- { scroll, if necessary, so that character in specified position is visible }
- procedure setSelectionRange (start, finish: integer);
- { set range of hilited text (used, for example in Cut and Copy commands) }
- function selectStart: integer;
- { starting position of hilited text }
- function selectEnd: integer;
- { ending position of hilited text; if selectStart and selectEnd are equal, then }
- { there is an insertion point rather than a hilited range }
- procedure doTab (TE: TEHandle);
- { for responding to a tab character }
-
- procedure doClear;
- procedure doCut;
- procedure doCopy;
- procedure doPaste;
- procedure doEditMenu (itemNum: integer);
- { These respond to edit menmu commands; doEditMenu simply routes }
- { one of the four preceding procedures }
-
- { OVERRIDEN METHODS: }
-
- procedure doContentClick (localPt: point;
- modifiers: longint);
- override;
- { respond to a user click on the text; this can move insertion point or }
- { set the selection range if the user drags the mouse }
- procedure doKey (ch: char;
- modifiers: longint); { respond to a user keystroke }
- override;
- procedure doRedraw (badRect: rect);
- override;
- procedure AdjustToNewSize;
- override;
- procedure doVScroll (dv: integer); { scrolls the text by dv lines }
- override;
- procedure doHScroll (dh: integer);
- override;
- procedure doActivate (active: boolean);
- override;
- procedure doClose; { disposes of TE then closes window }
- override;
- procedure idle; { calles TEIdle, if the text is not locked, to blink the insertion point }
- override;
-
- end;
-
-
- procedure twUpdateEditMenu (editMH: menuHandle);
- { Checks if the front window is an xTextWindow; if no, it appropriately enables }
- { and disables the Edit Menu commands; if not, all Edit Menu commands are }
- { disabled. This is provided as a convenience. }
-
-
- implementation
-
-
- var
- clickedWin: xTextWindow; { for use in ClickLoop procedure }
- clickSaveClip: RgnHandle;
-
- function ClickLoopProc: boolean;
- var
- newTopLine: integer;
- topLine: integer;
- savePort: GrafPtr;
- pt: point;
- dh: integer;
- begin
- GetPort(savePort);
- with clickedWin do begin { clickedWin must be set by doContentClick }
- SetPort(theWindow);
- GetMouse(pt);
- topLine := GetVVal;
- if (pt.v < TE^^.viewRect.top - 4) & (topLine > 0) then begin
- newTopLine := topLine - 1;
- if TE^^.SelStart <= TE^^.lineStarts[topLine] then
- TE^^.selStart := TE^^.lineStarts[newTopLine];
- end
- else if (pt.v > TE^^.viewRect.bottom + 4) & (topLine < linesInTE - linesPerPage) then begin
- newTopLine := topLine + 1;
- if TE^^.selEnd >= TE^^.lineStarts[TopLine + linesPerPage] then
- if newTopLine = linesInTE - linesPerPage then
- TE^^.selEnd := TE^^.TELength + 1
- else
- TE^^.selEnd := TE^^.lineStarts[newTopLine + linesPerPage]
- end
- else begin
- newTopLine := topLine
- end;
- if not (hasHScroll in features) then
- dh := 0
- else if pt.h < TE^^.viewRect.left - 4 then begin
- dh := pt.h - (TE^^.viewRect.left - 4);
- if dh < -12 then
- dh := -12;
- if GetHVal + dh < 0 then
- dh := -GetHVal;
- end
- else if pt.h > TE^^.viewRect.right + 4 then begin
- dh := pt.h - (TE^^.viewRect.right + 4);
- if dh > 12 then
- dh := 12;
- if GetHVal + dh > GetHMax then
- dh := GetHmax - GetHVal;
- end
- else
- dh := 0;
- if (dh <> 0) | (topLine <> newTopLine) then begin
- GetClip(clickSaveClip); { clickSaveClip must be newed by doContentClick }
- ClipRect(theWindow^.portRect);
- if topLine <> newTopLine then begin
- SetVVal(newTopLine);
- doVScroll(newTopLine - topLine)
- end;
- if dh <> 0 then begin
- SetHVal(GetHVal + dh);
- doHScroll(dh);
- end;
- SetClip(clickSaveClip);
- end;
- end;
- SetPort(savePort);
- ClickLoopProc := true;
- end;
-
-
- procedure xTextWindow.setDefaults;
- begin
- inherited setDefaults;
- setFeatures([hasGoAway, hasGrow, hasZoom, hasVScroll]);
- topTextOffset := 0;
- leftTextOffset := 0;
- maxChars := 10000;
- locked := false;
- tabCt := 0;
- end;
-
-
- procedure xTextWindow.openInRect (title: string;
- left, top, right, bottom: integer);
- var
- R: rect;
- savePort: GrafPtr;
- ch: cursHandle;
- width, height: integer;
- info: FontInfo;
- pointSize, fontNumber: integer;
- begin
- setDefaults;
- if minSize.v < 65 then
- minSize.v := 65;
- inherited doBasicOpen(title, left, top, right, bottom);
- GetPort(savePort);
- SetPort(theWindow);
- R := theWindow^.portRect;
- R.right := R.right - 15;
- R.left := R.left + leftTextOffset;
- R.top := R.top + topTextOffset;
- if hasHScroll in features then
- R.bottom := R.bottom - 15;
- InsetRect(R, 4, 4);
- if EmptyRect(R) then
- R := theWindow^.portRect;
- TE := TENew(R, R);
- if realFont(geneva, 12) then
- TextFont(geneva)
- else if realFont(monaco, 12) then
- TextFont(monaco)
- else
- TextFont(systemFont);
- GetFontInfo(info);
- TE^^.lineHeight := info.ascent + info.descent + info.leading;
- TE^^.fontAscent := info.ascent;
- TE^^.txFont := theWindow^.txFont;
- TE^^.txSize := theWindow^.txSize;
- if hasHScroll in Features then
- maxSize.h := 150 * CharWidth('0') + 1;
- hpixelsperline := 12;
- SetPort(savePort);
- linesPerPage := (R.bottom - R.top + 4) div TE^^.lineHeight;
- R.bottom := R.top + TE^^.lineHeight * linesPerPage;
- TE^^.viewRect := R;
- if hasHScroll in features then begin
- TE^^.crOnly := -1;
- SetHMax(maxSize.h - (theWindow^.portRect.right - theWindow^.portRect.left) - 1);
- end;
- SetLinesPerPage(4 * (theWindow^.portRect.right - theWindow^.portRect.left) div 5, linesPerPage);
- SetClikLoop(@ClickLoopProc, TE);
- linesInTE := 0;
- changed := false;
- trimmed := false;
- topLeftChar := 0;
- new(cursorHandler);
- cursorHandler.init;
- height := TE^^.viewRect.bottom - TE^^.viewRect.top;
- width := TE^^.viewRect.right - TE^^.viewRect.left;
- cursorHandler.install(self, leftTextOffset + 4, topTextOffset + 4, width, height);
- ch := GetCursor(iBeamCursor);
- if ch <> nil then
- cursorHandler.useCursor(ch^^);
- if locked then begin
- TEDeactivate(TE);
- cursorHandler.grayedOut := true;
- end;
- end;
-
- function CountTELines (TE: TEHandle): integer;
- var
- ct: integer;
- chars: CharsHandle;
- lastCh: char;
- begin
- ct := TE^^.nLines;
- if ct > 0 then begin
- chars := TEGetText(TE);
- lastCh := Chars^^[TE^^.teLength - 1];
- if lastCh = chr(13) then
- ct := ct + 1;
- end;
- CountTELines := ct;
- end;
-
- procedure CheckScroll (win: xTextWindow);
- var
- topLine, newTopLine: integer;
- begin
- with win do begin
- TopLine := GetVVal;
- newTopLine := topLine;
- if linesInTE <> CountTElines(TE) then begin
- linesInTE := CountTELines(TE);
- if linesInTE - linesPerPage > 0 then begin
- SetVMax(linesInTE - linesPerPage);
- if newTopLine > linesInTE - linesPerPage then
- newTopLine := linesInTE - linesPerPage
- end
- else begin
- SetVMax(0);
- newTopLine := 0;
- end;
- end;
- if TE^^.selStart < TE^^.lineStarts[newTopLine] then begin
- repeat
- newTopLine := newTopLine - 1
- until (newTopLine = 0) | (TE^^.selStart >= TE^^.lineStarts[newTopLine])
- end
- else if (newTopLine + linesPerPage < linesInTE) & (TE^^.selEnd >= TE^^.lineStarts[newTopLine + linesPerPage]) then begin
- repeat
- newTopLine := newTopLine + 1
- until (newTopLine + linesPerPage = linesInTE) | (TE^^.selEnd < TE^^.lineStarts[newTopLine + linesPerPage]);
- end;
- if (newTopLine <> topLine) then begin
- SetVVal(newTopLine);
- doVScroll(newTopLine - topLine);
- end;
- end;
- win.ScrollToSelection;
- end;
-
- procedure CheckTrim (win: xTextWindow);
- var
- line: integer;
- trimAmount: integer;
- pos: integer;
- saveSelStart, saveSelEnd: integer;
- chars: CharsHandle;
- i: integer;
- begin
- if win.maxChars > 30000 then
- win.maxChars := 30000
- else if win.maxChars < 3000 then
- win.maxChars := 3000;
- if win.TE^^.teLength > win.maxChars + 2000 then begin
- trimAmount := win.TE^^.teLength - win.maxChars;
- line := 1;
- while (line < win.TE^^.nLines) & (win.TE^^.lineStarts[line] < trimAmount) do
- line := line + 1;
- if line < win.TE^^.nLines then begin
- pos := win.TE^^.lineStarts[line] - 1;
- saveSelStart := win.TE^^.selStart - pos;
- if saveSelStart < 0 then
- saveSelStart := 0;
- saveSelEnd := win.TE^^.selEnd - pos;
- if saveSelEnd < 0 then
- saveSelEnd := 0;
- chars := TEGetText(win.TE);
- for i := pos to win.TE^^.teLength - 1 do
- chars^^[i - pos] := chars^^[i];
- SetHandleSize(Handle(chars), win.TE^^.teLength - pos);
- win.TE^^.teLength := win.TE^^.teLength - pos;
- TECalText(win.TE);
- TESetSelect(saveSelStart, saveSelEnd, win.TE);
- CheckScroll(win);
- win.trimmed := true;
- end;
- end;
- end;
-
-
- procedure xTextWindow.clearAllText;
- var
- R: Rect;
- savePort: GrafPtr;
- begin
- TESetSelect(0, 32000, TE);
- TEDelete(TE);
- R := theWindow^.portRect;
- R.right := R.right - 15;
- R.top := R.top + topTextOffset;
- R.left := R.left + leftTextOffset;
- R.bottom := R.bottom - 15;
- GetPort(savePort);
- SetPort(theWindow);
- InvalRect(R);
- SetPort(savePort);
- InsetRect(R, 4, 4);
- linesPerPage := (R.bottom - R.top + 4) div TE^^.lineHeight;
- R.bottom := R.top + TE^^.lineHeight * linesPerPage;
- vLinesPerPage := linesPerPage;
- TE^^.destRect := R;
- TE^^.viewRect := R;
- setVMax(0);
- setVVal(0);
- linesInTE := 0;
- topLeftChar := 0;
- changed := false;
- trimmed := false;
- end;
-
- procedure xTextWindow.installText (theText: CharsHandle);
- begin
- if GetHandleSize(handle(theText)) >= maxChars + 2000 then
- EXIT(installText);
- clearAllText;
- TE^^.hText := Handle(theText);
- TECalText(TE);
- linesInTE := CountTELines(TE);
- if linesInTE > linesPerPage then
- SetVMax(linesInTE - linesPerPage)
- else
- SetVMax(0);
- changed := false;
- trimmed := false;
- end;
-
- function xTextWindow.getText: CharsHandle;
- begin
- getText := TEGetText(TE);
- end;
-
- procedure xTextWindow.InsertString (str: string);
- begin
- if str <> '' then begin
- TEInsert(@str[1], length(str), TE);
- changed := true;
- CheckScroll(self);
- CheckTrim(self);
- end;
- end;
-
- procedure xTextWindow.appendString (str: string);
- begin
- setSelectionRange(maxint, maxint);
- insertString(str);
- end;
-
- procedure xTextWindow.appendCR;
- begin
- appendString(chr(13));
- end;
-
- function xTextWindow.dirty: boolean;
- begin
- dirty := changed
- end;
-
- procedure xTextWindow.declareClean;
- begin
- changed := false;
- trimmed := false;
- end;
-
- procedure xTextWindow.setFont (fontNumber, pointSize: integer);
- var
- savePort: GrafPtr;
- info: FontInfo;
- oldFont, oldSize: integer;
- line: integer;
- begin
- GetPort(savePort);
- SetPort(theWindow);
- oldFont := theWindow^.txFont;
- oldSize := theWindow^.txSize;
- TextFont(fontNumber);
- TextSize(pointSize);
- GetFontInfo(info);
- TE^^.lineHeight := info.ascent + info.descent + info.leading;
- TE^^.fontAscent := info.ascent;
- TE^^.txFont := theWindow^.txFont;
- TE^^.txSize := theWindow^.txSize;
- TextFont(oldFont);
- TextSize(oldSize);
- AdjustToNewSize;
- InvalRect(TE^^.viewRect);
- SetPort(savePort);
- end;
-
- procedure xTextWindow.scrollToSelection;
- begin
- scrollTo(TE^^.selStart);
- end;
-
- procedure xTextWindow.scrollTo (position: integer);
- var
- topLine: integer;
- n: integer;
- line: integer;
- w, dh: integer;
- SavePort: GrafPtr;
- hText: CharsHandle;
- oldFont: integer;
- oldSize: integer;
- begin
- topLine := GetVVal;
- if (position < TE^^.lineStarts[topLine]) then begin
- n := topLine;
- repeat
- n := n - 1
- until (n = 0) | (position >= TE^^.lineStarts[n]);
- line := n;
- SetVVal(n);
- doVScroll(n - topLine);
- end
- else begin
- n := topLine;
- repeat
- n := n + 1
- until (n >= linesInTE) | (position < TE^^.lineStarts[n]);
- line := n - 1;
- if (topLine + linesPerPage < linesInTE) & (position >= TE^^.lineStarts[topLine + linesPerPage]) then begin
- n := n - linesPerPage;
- SetVVal(n);
- doVScroll(n - topLine);
- end
- end;
- GetPort(SavePort);
- SetPort(theWindow);
- oldFont := theWindow^.txFont;
- oldSize := theWindow^.txSize;
- TextFont(TE^^.txFont);
- TextSize(TE^^.txSize);
- w := 0;
- n := TE^^.lineStarts[line];
- {$ifc option(debug)}
- if n > position then begin
- TellUser('Bad logic detected in procedure ScrollTo. Program is being terminated');
- halt;
- end;
- {$endc}
- hText := GetText;
- while n < position do begin
- w := w + CharWidth(hText^^[n]);
- n := n + 1;
- {$ifc option(debug)}
- if ((line + 1 < linesInTE) & (n >= TE^^.lineStarts[line + 1])) | (n > TE^^.teLength) then begin
- TellUser('Bad logic detected in procedure ScrollTo. Program is being terminated');
- halt;
- end
- {$endc}
- end;
- if hasHScroll in features then begin
- if w + TE^^.destRect.left < TE^^.viewRect.left + 24 then begin
- dh := w + TE^^.destRect.left - (TE^^.viewRect.left + 24);
- if GetHVal + dh < 0 then
- dh := -GetHVal;
- end
- else if w + TE^^.destRect.left >= TE^^.viewRect.right then begin
- dh := w + TE^^.destRect.left - (TE^^.viewRect.right - 1);
- if GetHVal + dh > GetHMax then
- dh := GetHMax - GetHVal;
- end
- else
- dh := 0;
- if dh <> 0 then begin
- SetHVal(GetHVal + dh);
- doHScroll(dh);
- end;
- end;
- TextFont(oldFont);
- TextSize(oldSize);
- SetPort(SavePort);
- end;
-
- procedure xTextWindow.setSelectionRange (start, finish: integer);
- begin
- TESetSelect(start, finish, TE);
- end;
-
- function xTextWindow.selectStart: integer;
- begin
- selectStart := TE^^.selStart;
- end;
-
- function xTextWindow.selectEnd: integer;
- begin
- selectEnd := TE^^.selEnd;
- end;
-
- procedure twUpdateEditMenu (editMH: menuHandle);
- var
- win: WindowPtr;
- xWin: xWindow;
- i: integer;
- begin
- win := FrontWindow;
- if (win <> nil) & (WindowPeek(win)^.windowKind < 0) then begin { it's a desk accessory }
- EnableItem(editMH, 1); { Enable standard items in Edit menu }
- for i := 3 to 6 do
- EnableItem(editMH, i);
- DisableItem(editMH, 8);
- DisableItem(editMH, 9);
- EXIT(twUpdateEditMenu);
- end;
- DisableItem(editMH, 1);
- DisableItem(editMH, 3);
- DisableItem(editMH, 4);
- DisableItem(editMH, 5);
- DisableItem(editMH, 6);
- DisableItem(editMH, 8);
- DisableItem(editMH, 9);
- if (win <> nil) & (Window2XWindow(win, xWin)) then begin
- if member(xWin, xTextWindow) & not xTextWindow(xWin).locked then begin
- if xTextWindow(xWin).TE^^.selStart < xTextWindow(xWin).TE^^.selEnd then begin
- EnableItem(editMH, 3);
- EnableItem(editMH, 4);
- EnableItem(editMH, 6);
- end;
- if TEGetScrapLen > 0 then
- EnableItem(editMH, 5);
- if xTextWindow(xWin).TE^^.teLength > 0 then begin
- EnableItem(editMH, 8);
- EnableItem(editMH, 9);
- end;
- end
- end;
- end;
-
-
- procedure xTextWindow.doClear;
- begin
- if not locked & (TE^^.selEnd > TE^^.selStart) then begin
- TEDelete(TE);
- changed := true;
- CheckScroll(self);
- end;
- end;
-
- procedure xTextWindow.doCut;
- begin
- if not locked & (TE^^.selEnd > TE^^.selStart) then begin
- TECut(TE);
- changed := true;
- CheckScroll(self);
- end;
- end;
-
- procedure xTextWindow.doCopy;
- begin
- if not locked then begin
- TECopy(TE);
- end;
- end;
-
- procedure xTextWindow.doPaste;
- begin
- if not locked & (TEGetScrapLen > 0) then
- if TEGetScrapLen + TE^^.teLength - (TE^^.selEnd - TE^^.selStart) > 32000 then
- SysBeep(5)
- else begin
- TEPaste(TE);
- changed := true;
- CheckScroll(self);
- CheckTrim(self);
- end;
- end;
-
- procedure xTextWindow.doEditMenu (itemNum: integer);
- begin
- case itemNum of
- 3:
- doCut;
- 4:
- doCopy;
- 5:
- doPaste;
- 6:
- doClear;
- 8:
- setSelectionRange(0, 32000);
- 9:
- clearAllText;
- end;
- end;
-
- procedure xTextWindow.doContentClick (localPt: point;
- modifiers: longint);
- var
- shifted: boolean;
- begin
- if locked | (localPt.v < TopTextOffset) | (localPt.v > theWindow^.portrect.bottom - 15) | (localPt.h < LeftTextOffset) | (localPt.h > theWindow^.portRect.right - 15) then
- inherited doContentClick(localPt, modifiers)
- else begin
- clickedWin := self;
- HLock(Handle(clickedWin));
- clickSaveClip := NewRgn;
- shifted := BitAnd(modifiers, shiftKey) <> 0;
- TEClick(localPt, shifted, TE);
- DisposeRgn(clickSaveClip);
- HUnLock(Handle(clickedWin));
- end;
- end;
-
- procedure xTextWindow.doTab (TE: TEHandle);
- var
- n: integer;
- pos: integer;
- i, ct, max: integer;
- begin
- n := 1;
- pos := TE^^.selStart;
- if (pos = 0) | (CharsHandle(TE^^.hText)^^[pos - 1] = chr(13)) then
- ct := tabCt
- else begin
- max := TE^^.nLines;
- while (n < max) & (TE^^.lineStarts[n] < pos) do
- n := n + 1;
- ct := tabCt - ((pos - TE^^.lineStarts[n - 1]) mod tabCt);
- end;
- for i := 1 to ct do
- TEKey(' ', TE);
- end;
-
- procedure xTextWindow.doKey (ch: char;
- modifiers: longint);
- var
- start, finish: integer;
- begin
- if locked then
- inherited doKey(ch, modifiers)
- else begin
- if ch = chr(3) then
- ch := chr(13);
- if (ch = chr(9)) & (tabCt > 1) then
- doTab(TE)
- else if (ch in [chr($1c)..chr($1f)]) & (TE^^.selEnd > TE^^.selStart) then begin
- start := TE^^.selStart;
- finish := TE^^.selEnd;
- if ch = chr($1e) then begin
- SetSelectionRange(start, start);
- TEKey(ch, TE);
- end
- else if ch = chr($1c) then begin
- SetSelectionRange(start, start);
- end
- else if ch = chr($1f) then begin
- SetSelectionRange(finish, finish);
- TEKey(ch, TE)
- end
- else begin
- SetSelectionRange(finish, finish);
- end
- end
- else
- TEKey(ch, TE);
- if not (ch in [chr($1c)..chr($1f)]) then
- changed := true;
- CheckScroll(self);
- CheckTrim(self);
- end;
- end;
-
- procedure xTextWindow.doRedraw (badRect: rect);
- begin
- inherited doRedraw(badRect);
- TEUpdate(badRect, TE);
- end;
-
- procedure xTextWindow.AdjustToNewSize;
- var
- R, V: Rect;
- hv: integer;
- line: integer;
- width, height: integer;
- begin
- inherited AdjustToNewSize;
- R := theWindow^.portRect;
- R.right := R.right - 15;
- R.top := R.top + topTextOffset;
- R.left := R.left + leftTextOffset;
- if hasHScroll in features then
- R.bottom := R.bottom - 15;
- InsetRect(R, 4, 4);
- TE^^.destRect := R;
- TE^^.viewRect := R;
- linesPerPage := (R.bottom - R.top + 4) div TE^^.lineHeight;
- TECalText(TE);
- linesInTE := CountTELines(TE);
- line := 0;
- V := R;
- if hasHScroll in features then begin
- hv := GetHVal;
- SetHMax(maxSize.h - (theWindow^.portRect.right - theWindow^.portRect.left) - 1);
- if hv > GetHMax then begin
- hv := GetHMax;
- SetHVal(hv);
- end;
- V.left := V.left - hv;
- end;
- if linesInTE - linesPerPage > 0 then begin
- while (line < TE^^.nLines) & (TE^^.lineStarts[line + 1] <= topLeftChar) do
- line := line + 1;
- if line > linesInTE - linesPerPage then
- line := linesInTE - linesPerPage;
- V.top := V.top - line * TE^^.lineHeight;
- topLeftChar := TE^^.lineStarts[line];
- SetVMax(linesInTE - linesPerPage);
- end
- else begin
- SetVMax(0);
- topLeftChar := 0;
- end;
- R.bottom := R.top + TE^^.lineHeight * linesPerPage;
- TE^^.destRect := V;
- TE^^.viewRect := R;
- SetVVal(line);
- if linesPerPage <= 3 then
- SetLinesPerPage(4 * (theWindow^.portRect.right - theWindow^.portRect.left) div 5, 1)
- else
- SetLinesPerPage(4 * (theWindow^.portRect.right - theWindow^.portRect.left) div 5, linesPerPage - 2);
- height := TE^^.viewRect.bottom - TE^^.viewRect.top;
- width := TE^^.viewRect.right - TE^^.viewRect.left;
- cursorHandler.move(leftTextOffset + 4, topTextOffset + 4);
- cursorHandler.setSize(width, height);
- end;
-
- procedure xTextWindow.doVScroll (dv: integer);
- var
- newLine: integer;
- topLine: integer;
- begin
- if dv <> 0 then begin
- TEPinScroll(0, -TE^^.lineHeight * dv, TE);
- topLine := GetVVal;
- topLeftChar := TE^^.lineStarts[topLine];
- end;
- end;
-
- procedure xTextWindow.doHScroll (dh: integer);
- begin
- if (dh <> 0) & (hasHScroll in features) then
- TEScroll(-dh, 0, TE);
- end;
-
- procedure xTextWindow.doActivate (active: boolean);
- begin
- inherited doActivate(active);
- if not locked then
- if active then
- TEActivate(TE)
- else
- TEDeactivate(TE);
- end;
-
- procedure xTextWindow.lock;
- begin
- if not locked then begin
- TEDeactivate(TE);
- locked := true;
- cursorHandler.grayedOut := true;
- end;
- end;
-
- procedure xTextWindow.unlock;
- begin
- if locked then begin
- if (theWindow <> nil) & (theWindow = FrontWindow) then
- TEActivate(TE);
- locked := false;
- cursorHandler.grayedOut := false;
- end;
- end;
-
- procedure xTextWindow.doClose;
- begin
- TEDispose(TE);
- inherited doClose;
- end;
-
- procedure xTextWindow.idle;
- begin
- if locked then
- inherited idle
- else
- TEIdle(TE);
- end;
-
- end.